library(tidyverse)
library(httr)
library(sf)
library(ggplot2)
library(tmap)
library(plotly)
library(glue)

Define common columns

cols <- c(
  "Date",
  "Regio",
  "Period",
  "Population",
  "Deaths",
  "MortalityRate")

Load historical data for flu dataset

cols.historic <-
  c(
    cols,
    "Year"
  )

data.historic <- read_rds("../results/data.Rds") %>% rename(Regio = RegioS) %>% select(cols.historic)

# data.flu2018 <- data.historic %>% 
#   filter(Year == 2018 | Year == 2017) %>% 
#   group_by(Year) %>%
#   mutate(
#     LastPeriod = max(Period, na.rm = T),
#     Period = if_else(Year == 2017 & Period == LastPeriod, 0, Period),
#   ) %>%
#   ungroup() %>%
#   mutate(Year = if_else(Period == 0, 2018, Year)) %>%
#   filter(Year == 2018) %>%
#   rename(Flu2018 = MortalityRate)

Additional RIVM data

data.rivm <- read_rds("../results/rivm.Rds") %>% rename(Rivm = Deaths)

Data for 2020 corona crisis

cols.corona <-
  c(
    cols,
    "ExpectedMortality", "AvgMortality", "UnexpectedMortality", "ExcessiveMortality", "Flu2018"
  )

data.corona <- read_rds("../results/data.corona.Rds") %>% rename(Regio = RegioS) %>% select(cols.corona) %>%
  full_join(data.rivm, by = c("Regio", "Date", "Period")) %>%
  drop_na(Date)

data.corona %>% filter(Regio == "NL") %>% arrange(Date)

Geographical entities

areas <- GET("https://opendata.arcgis.com/datasets/e1f0dd70abcb4fceabbc43412e43ad4b_0.geojson") %>% content(as = "text") %>%
  read_sf() %>%
  rename(RegioS = Gemeentecode) %>% 
  arrange(Gemeentenaam) 
No encoding supplied: defaulting to UTF-8.
write_rds(areas, "../results/plots/areas.Rds")

Create a timeline and add splines for smooth charts

# Do some interpolation
dates <- data.corona %>% drop_na("Period", "Date") %>% distinct(Date) %>% pull("Date")
fields <- c("MortalityRate", "ExpectedMortality", "AvgMortality", "Flu2018", "DeathsUnexpected", "DeathsAboveAvg", "Rivm", "Deaths")
days <- data.frame(Date = seq(min(dates), to = max(dates), by = "days")) %>%
  crossing(data.corona %>% select(Regio) %>% distinct()) %>%
  crossing(fields) %>%
  set_names(c("Date", "Regio", "Variable"))

data.mort <- data.corona %>% 
  mutate(
    DeathsUnexpected = UnexpectedMortality * Population / 100000,
    DeathsAboveAvg = ExcessiveMortality * Population / 100000,
  ) %>%
  gather("Variable", "Value", fields) %>%
  drop_na(Regio, Variable, Date) %>%
  full_join(days) %>%
  group_by(Regio, Variable) %>%
  filter(sum(!is.na(Value)) > 0) %>%
  # summarise(n = n()) %>% arrange(n)
  mutate(
    Interpolated = approx(Date, Value, xout=Date)$y,
    Absolute = if_else(Variable == "MortalityRate", Value * Population / 100000, as.double(NA))
  ) %>%
  ungroup() %>%
  select("Regio", "Date", "Period", "Variable", "Value", "Interpolated", "Absolute")
Joining, by = c("Date", "Regio", "Variable")
data.mort %>% filter(Regio == "NL") %>% arrange(Date)

write_rds(data.mort, "../results/plots/mortovertime.Rds")

Example 1

x <- data.mort %>%
  filter(Variable %in% c("MortalityRate", "ExpectedMortality", "AvgMortality", "Flu2018")) %>%
  filter(Regio == "GM0345")

tooltip <- ("<b>{Date}</b>
Mortality rate: {floor(Value)}
Deaths: {floor(Absolute)}"
)

ggplotly(tooltip = "text", ggplot(
      x,
      aes(
        group = Variable,
        color = Variable,
        text = tooltip %>% glue()
      )
    ) +
      geom_point(aes(x = Date, y = Value)) +
      geom_line(aes(x = Date, y = Interpolated)) +
      labs(x = "Period (weeks)" %>% glue(), y = "Deaths by 100.000 inhabitants") +
      theme_minimal() +
      theme(legend.title = element_blank())
)

Example 2

x <- data.mort %>% 
  filter(Variable %in% c("Rivm", "DeathsAboveAvg", "DeathsUnexpected")) %>%
  filter(Regio == "NL")


tooltip <- ("<b>{Date}</b>
Deaths: {floor(Interpolated)}")

ggplotly(ggplot(
  x,
  aes(
    group = Variable,
    color = Variable,
    text =  tooltip %>% glue()
  )
) +
  geom_line(aes(x = Date, y = Interpolated)) +
  geom_point(aes(x = Date, y = Value)) +
  labs(x = "Period (weeks)" %>% glue(), y = "Absolute deaths") +
  theme_minimal() +
  theme(legend.title = element_blank()) +
  scale_color_brewer(palette = "Set2"),

  tooltip = "text"
)

Spatial dataset

data.spatial_absolute <- areas %>% left_join(data.corona, by = c("RegioS" = "Regio")) %>% 
    mutate(
      ActualMortality = round(MortalityRate * Population / 100000),
      ExpectedMortality = round(ExpectedMortality * Population / 100000),
      AvgMortality = round(AvgMortality * Population / 100000),
      UnexpectedMortality = round(UnexpectedMortality * Population / 100000),
      ExcessiveMortality = round(ExcessiveMortality * Population / 100000),
    ) 

write_rds(data.spatial_absolute, "../results/plots/spatial_absolute.Rds")

Example

tm_shape(data.spatial_absolute %>% filter(Period == 4)) +
  tm_polygons(
    col = "MortalityRate",
    id = "Gemeentenaam",
    title = "Mortality rate by municipality"
  )

Summary table

year_high_mort <- data.historic %>% group_by(Regio, Year) %>% 
  summarise(MortalityRate = mean(MortalityRate)) %>% 
  arrange(desc(MortalityRate)) %>%
  slice(1) %>% arrange(Regio) %>% ungroup() %>%
  select(YearHighestMort = Year, Regio)

data.summary <- data.mort %>% 
      filter(Period > 0 & Variable %in% c("Deaths", "Rivm", "DeathsAboveAvg", "DeathsUnexpected")) %>%
      group_by(Regio, Variable) %>%
      summarise(Value = floor(sum(Value, na.rm = T))) %>%
      spread(Variable, Value) %>%
      ungroup() %>%
      left_join(year_high_mort)
Joining, by = "Regio"
write_rds(data.summary, "../results/plots/summary.Rds")

data.mort %>% 
  filter(Regio == "GM0345" & Variable %in% c("Rivm")) %>% arrange(Date) %>% 
  group_by(Regio, Variable) %>% summarise(Value = sum(Value, na.rm = T)) %>% spread(Variable, Value)
data.summary %>% filter(Regio == "GM0345")
LS0tDQp0aXRsZTogIlByZXByb2Nlc3MgZGF0YSBmb3IgcGxvdHRpbmcgaW4gdGhlIGRhc2hib2FyZCINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGh0dHIpDQpsaWJyYXJ5KHNmKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeSh0bWFwKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KGdsdWUpDQpgYGANCg0KIyMjIERlZmluZSBjb21tb24gY29sdW1ucw0KDQpgYGB7cn0NCmNvbHMgPC0gYygNCiAgIkRhdGUiLA0KICAiUmVnaW8iLA0KICAiUGVyaW9kIiwNCiAgIlBvcHVsYXRpb24iLA0KICAiRGVhdGhzIiwNCiAgIk1vcnRhbGl0eVJhdGUiKQ0KYGBgDQoNCiMjIyBMb2FkIGhpc3RvcmljYWwgZGF0YSBmb3IgZmx1IGRhdGFzZXQNCg0KYGBge3J9DQpjb2xzLmhpc3RvcmljIDwtDQogIGMoDQogICAgY29scywNCiAgICAiWWVhciINCiAgKQ0KDQpkYXRhLmhpc3RvcmljIDwtIHJlYWRfcmRzKCIuLi9yZXN1bHRzL2RhdGEuUmRzIikgJT4lIHJlbmFtZShSZWdpbyA9IFJlZ2lvUykgJT4lIHNlbGVjdChjb2xzLmhpc3RvcmljKQ0KDQojIGRhdGEuZmx1MjAxOCA8LSBkYXRhLmhpc3RvcmljICU+JSANCiMgICBmaWx0ZXIoWWVhciA9PSAyMDE4IHwgWWVhciA9PSAyMDE3KSAlPiUgDQojICAgZ3JvdXBfYnkoWWVhcikgJT4lDQojICAgbXV0YXRlKA0KIyAgICAgTGFzdFBlcmlvZCA9IG1heChQZXJpb2QsIG5hLnJtID0gVCksDQojICAgICBQZXJpb2QgPSBpZl9lbHNlKFllYXIgPT0gMjAxNyAmIFBlcmlvZCA9PSBMYXN0UGVyaW9kLCAwLCBQZXJpb2QpLA0KIyAgICkgJT4lDQojICAgdW5ncm91cCgpICU+JQ0KIyAgIG11dGF0ZShZZWFyID0gaWZfZWxzZShQZXJpb2QgPT0gMCwgMjAxOCwgWWVhcikpICU+JQ0KIyAgIGZpbHRlcihZZWFyID09IDIwMTgpICU+JQ0KIyAgIHJlbmFtZShGbHUyMDE4ID0gTW9ydGFsaXR5UmF0ZSkNCg0KYGBgDQoNCiMjIyBBZGRpdGlvbmFsIFJJVk0gZGF0YQ0KDQpgYGB7cn0NCmRhdGEucml2bSA8LSByZWFkX3JkcygiLi4vcmVzdWx0cy9yaXZtLlJkcyIpICU+JSByZW5hbWUoUml2bSA9IERlYXRocykNCmBgYA0KDQojIyMgRGF0YSBmb3IgMjAyMCBjb3JvbmEgY3Jpc2lzDQoNCmBgYHtyfQ0KY29scy5jb3JvbmEgPC0NCiAgYygNCiAgICBjb2xzLA0KICAgICJFeHBlY3RlZE1vcnRhbGl0eSIsICJBdmdNb3J0YWxpdHkiLCAiVW5leHBlY3RlZE1vcnRhbGl0eSIsICJFeGNlc3NpdmVNb3J0YWxpdHkiLCAiRmx1MjAxOCINCiAgKQ0KDQpkYXRhLmNvcm9uYSA8LSByZWFkX3JkcygiLi4vcmVzdWx0cy9kYXRhLmNvcm9uYS5SZHMiKSAlPiUgcmVuYW1lKFJlZ2lvID0gUmVnaW9TKSAlPiUgc2VsZWN0KGNvbHMuY29yb25hKSAlPiUNCiAgZnVsbF9qb2luKGRhdGEucml2bSwgYnkgPSBjKCJSZWdpbyIsICJEYXRlIiwgIlBlcmlvZCIpKSAlPiUNCiAgZHJvcF9uYShEYXRlKQ0KDQpkYXRhLmNvcm9uYSAlPiUgZmlsdGVyKFJlZ2lvID09ICJOTCIpICU+JSBhcnJhbmdlKERhdGUpDQpgYGANCg0KIyMjIEdlb2dyYXBoaWNhbCBlbnRpdGllcw0KDQpgYGB7cn0NCmFyZWFzIDwtIEdFVCgiaHR0cHM6Ly9vcGVuZGF0YS5hcmNnaXMuY29tL2RhdGFzZXRzL2UxZjBkZDcwYWJjYjRmY2VhYmJjNDM0MTJlNDNhZDRiXzAuZ2VvanNvbiIpICU+JSBjb250ZW50KGFzID0gInRleHQiKSAlPiUNCiAgcmVhZF9zZigpICU+JQ0KICByZW5hbWUoUmVnaW9TID0gR2VtZWVudGVjb2RlKSAlPiUgDQogIGFycmFuZ2UoR2VtZWVudGVuYWFtKSANCg0Kd3JpdGVfcmRzKGFyZWFzLCAiLi4vcmVzdWx0cy9wbG90cy9hcmVhcy5SZHMiKQ0KYGBgDQoNCiMjIyBDcmVhdGUgYSB0aW1lbGluZSBhbmQgYWRkIHNwbGluZXMgZm9yIHNtb290aCBjaGFydHMNCg0KYGBge3J9DQojIERvIHNvbWUgaW50ZXJwb2xhdGlvbg0KZGF0ZXMgPC0gZGF0YS5jb3JvbmEgJT4lIGRyb3BfbmEoIlBlcmlvZCIsICJEYXRlIikgJT4lIGRpc3RpbmN0KERhdGUpICU+JSBwdWxsKCJEYXRlIikNCmZpZWxkcyA8LSBjKCJNb3J0YWxpdHlSYXRlIiwgIkV4cGVjdGVkTW9ydGFsaXR5IiwgIkF2Z01vcnRhbGl0eSIsICJGbHUyMDE4IiwgIkRlYXRoc1VuZXhwZWN0ZWQiLCAiRGVhdGhzQWJvdmVBdmciLCAiUml2bSIsICJEZWF0aHMiKQ0KZGF5cyA8LSBkYXRhLmZyYW1lKERhdGUgPSBzZXEobWluKGRhdGVzKSwgdG8gPSBtYXgoZGF0ZXMpLCBieSA9ICJkYXlzIikpICU+JQ0KICBjcm9zc2luZyhkYXRhLmNvcm9uYSAlPiUgc2VsZWN0KFJlZ2lvKSAlPiUgZGlzdGluY3QoKSkgJT4lDQogIGNyb3NzaW5nKGZpZWxkcykgJT4lDQogIHNldF9uYW1lcyhjKCJEYXRlIiwgIlJlZ2lvIiwgIlZhcmlhYmxlIikpDQoNCmRhdGEubW9ydCA8LSBkYXRhLmNvcm9uYSAlPiUgDQogIG11dGF0ZSgNCiAgICBEZWF0aHNVbmV4cGVjdGVkID0gVW5leHBlY3RlZE1vcnRhbGl0eSAqIFBvcHVsYXRpb24gLyAxMDAwMDAsDQogICAgRGVhdGhzQWJvdmVBdmcgPSBFeGNlc3NpdmVNb3J0YWxpdHkgKiBQb3B1bGF0aW9uIC8gMTAwMDAwLA0KICApICU+JQ0KICBnYXRoZXIoIlZhcmlhYmxlIiwgIlZhbHVlIiwgZmllbGRzKSAlPiUNCiAgZHJvcF9uYShSZWdpbywgVmFyaWFibGUsIERhdGUpICU+JQ0KICBmdWxsX2pvaW4oZGF5cykgJT4lDQogIGdyb3VwX2J5KFJlZ2lvLCBWYXJpYWJsZSkgJT4lDQogIGZpbHRlcihzdW0oIWlzLm5hKFZhbHVlKSkgPiAwKSAlPiUNCiAgIyBzdW1tYXJpc2UobiA9IG4oKSkgJT4lIGFycmFuZ2UobikNCiAgbXV0YXRlKA0KICAgIEludGVycG9sYXRlZCA9IGFwcHJveChEYXRlLCBWYWx1ZSwgeG91dD1EYXRlKSR5LA0KICAgIEFic29sdXRlID0gaWZfZWxzZShWYXJpYWJsZSA9PSAiTW9ydGFsaXR5UmF0ZSIsIFZhbHVlICogUG9wdWxhdGlvbiAvIDEwMDAwMCwgYXMuZG91YmxlKE5BKSkNCiAgKSAlPiUNCiAgdW5ncm91cCgpICU+JQ0KICBzZWxlY3QoIlJlZ2lvIiwgIkRhdGUiLCAiUGVyaW9kIiwgIlZhcmlhYmxlIiwgIlZhbHVlIiwgIkludGVycG9sYXRlZCIsICJBYnNvbHV0ZSIpDQoNCmRhdGEubW9ydCAlPiUgZmlsdGVyKFJlZ2lvID09ICJOTCIpICU+JSBhcnJhbmdlKERhdGUpDQoNCndyaXRlX3JkcyhkYXRhLm1vcnQsICIuLi9yZXN1bHRzL3Bsb3RzL21vcnRvdmVydGltZS5SZHMiKQ0KYGBgDQoNCiMjIyMgRXhhbXBsZSAxDQoNCmBgYHtyIHB1cmw9Rn0NCnggPC0gZGF0YS5tb3J0ICU+JQ0KICBmaWx0ZXIoVmFyaWFibGUgJWluJSBjKCJNb3J0YWxpdHlSYXRlIiwgIkV4cGVjdGVkTW9ydGFsaXR5IiwgIkF2Z01vcnRhbGl0eSIsICJGbHUyMDE4IikpICU+JQ0KICBmaWx0ZXIoUmVnaW8gPT0gIkdNMDM0NSIpDQoNCnRvb2x0aXAgPC0gKCI8Yj57RGF0ZX08L2I+DQpNb3J0YWxpdHkgcmF0ZToge2Zsb29yKFZhbHVlKX0NCkRlYXRoczoge2Zsb29yKEFic29sdXRlKX0iDQopDQoNCmdncGxvdGx5KHRvb2x0aXAgPSAidGV4dCIsIGdncGxvdCgNCiAgICAgIHgsDQogICAgICBhZXMoDQogICAgICAgIGdyb3VwID0gVmFyaWFibGUsDQogICAgICAgIGNvbG9yID0gVmFyaWFibGUsDQogICAgICAgIHRleHQgPSB0b29sdGlwICU+JSBnbHVlKCkNCiAgICAgICkNCiAgICApICsNCiAgICAgIGdlb21fcG9pbnQoYWVzKHggPSBEYXRlLCB5ID0gVmFsdWUpKSArDQogICAgICBnZW9tX2xpbmUoYWVzKHggPSBEYXRlLCB5ID0gSW50ZXJwb2xhdGVkKSkgKw0KICAgICAgbGFicyh4ID0gIlBlcmlvZCAod2Vla3MpIiAlPiUgZ2x1ZSgpLCB5ID0gIkRlYXRocyBieSAxMDAuMDAwIGluaGFiaXRhbnRzIikgKw0KICAgICAgdGhlbWVfbWluaW1hbCgpICsNCiAgICAgIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkNCikNCmBgYA0KDQojIyMjIEV4YW1wbGUgMg0KDQpgYGB7ciBwdXJsPUZ9DQp4IDwtIGRhdGEubW9ydCAlPiUgDQogIGZpbHRlcihWYXJpYWJsZSAlaW4lIGMoIlJpdm0iLCAiRGVhdGhzQWJvdmVBdmciLCAiRGVhdGhzVW5leHBlY3RlZCIpKSAlPiUNCiAgZmlsdGVyKFJlZ2lvID09ICJOTCIpDQoNCg0KdG9vbHRpcCA8LSAoIjxiPntEYXRlfTwvYj4NCkRlYXRoczoge2Zsb29yKEludGVycG9sYXRlZCl9IikNCg0KZ2dwbG90bHkoZ2dwbG90KA0KICB4LA0KICBhZXMoDQogICAgZ3JvdXAgPSBWYXJpYWJsZSwNCiAgICBjb2xvciA9IFZhcmlhYmxlLA0KICAgIHRleHQgPSAgdG9vbHRpcCAlPiUgZ2x1ZSgpDQogICkNCikgKw0KICBnZW9tX2xpbmUoYWVzKHggPSBEYXRlLCB5ID0gSW50ZXJwb2xhdGVkKSkgKw0KICBnZW9tX3BvaW50KGFlcyh4ID0gRGF0ZSwgeSA9IFZhbHVlKSkgKw0KICBsYWJzKHggPSAiUGVyaW9kICh3ZWVrcykiICU+JSBnbHVlKCksIHkgPSAiQWJzb2x1dGUgZGVhdGhzIikgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpICsNCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiU2V0MiIpLA0KDQogIHRvb2x0aXAgPSAidGV4dCINCikNCmBgYA0KDQojIyMgU3BhdGlhbCBkYXRhc2V0DQoNCmBgYHtyfQ0KZGF0YS5zcGF0aWFsX2Fic29sdXRlIDwtIGFyZWFzICU+JSBsZWZ0X2pvaW4oZGF0YS5jb3JvbmEsIGJ5ID0gYygiUmVnaW9TIiA9ICJSZWdpbyIpKSAlPiUgDQogICAgbXV0YXRlKA0KICAgICAgQWN0dWFsTW9ydGFsaXR5ID0gcm91bmQoTW9ydGFsaXR5UmF0ZSAqIFBvcHVsYXRpb24gLyAxMDAwMDApLA0KICAgICAgRXhwZWN0ZWRNb3J0YWxpdHkgPSByb3VuZChFeHBlY3RlZE1vcnRhbGl0eSAqIFBvcHVsYXRpb24gLyAxMDAwMDApLA0KICAgICAgQXZnTW9ydGFsaXR5ID0gcm91bmQoQXZnTW9ydGFsaXR5ICogUG9wdWxhdGlvbiAvIDEwMDAwMCksDQogICAgICBVbmV4cGVjdGVkTW9ydGFsaXR5ID0gcm91bmQoVW5leHBlY3RlZE1vcnRhbGl0eSAqIFBvcHVsYXRpb24gLyAxMDAwMDApLA0KICAgICAgRXhjZXNzaXZlTW9ydGFsaXR5ID0gcm91bmQoRXhjZXNzaXZlTW9ydGFsaXR5ICogUG9wdWxhdGlvbiAvIDEwMDAwMCksDQogICAgKSANCg0Kd3JpdGVfcmRzKGRhdGEuc3BhdGlhbF9hYnNvbHV0ZSwgIi4uL3Jlc3VsdHMvcGxvdHMvc3BhdGlhbF9hYnNvbHV0ZS5SZHMiKQ0KYGBgDQoNCiMjIyMgRXhhbXBsZQ0KDQpgYGB7cn0NCnRtX3NoYXBlKGRhdGEuc3BhdGlhbF9hYnNvbHV0ZSAlPiUgZmlsdGVyKFBlcmlvZCA9PSA0KSkgKw0KICB0bV9wb2x5Z29ucygNCiAgICBjb2wgPSAiTW9ydGFsaXR5UmF0ZSIsDQogICAgaWQgPSAiR2VtZWVudGVuYWFtIiwNCiAgICB0aXRsZSA9ICJNb3J0YWxpdHkgcmF0ZSBieSBtdW5pY2lwYWxpdHkiDQogICkNCmBgYA0KIyMjIFN1bW1hcnkgdGFibGUNCg0KYGBge3J9DQp5ZWFyX2hpZ2hfbW9ydCA8LSBkYXRhLmhpc3RvcmljICU+JSBncm91cF9ieShSZWdpbywgWWVhcikgJT4lIA0KICBzdW1tYXJpc2UoTW9ydGFsaXR5UmF0ZSA9IG1lYW4oTW9ydGFsaXR5UmF0ZSkpICU+JSANCiAgYXJyYW5nZShkZXNjKE1vcnRhbGl0eVJhdGUpKSAlPiUNCiAgc2xpY2UoMSkgJT4lIGFycmFuZ2UoUmVnaW8pICU+JSB1bmdyb3VwKCkgJT4lDQogIHNlbGVjdChZZWFySGlnaGVzdE1vcnQgPSBZZWFyLCBSZWdpbykNCg0KZGF0YS5zdW1tYXJ5IDwtIGRhdGEubW9ydCAlPiUgDQogICAgICBmaWx0ZXIoUGVyaW9kID4gMCAmIFZhcmlhYmxlICVpbiUgYygiRGVhdGhzIiwgIlJpdm0iLCAiRGVhdGhzQWJvdmVBdmciLCAiRGVhdGhzVW5leHBlY3RlZCIpKSAlPiUNCiAgICAgIGdyb3VwX2J5KFJlZ2lvLCBWYXJpYWJsZSkgJT4lDQogICAgICBzdW1tYXJpc2UoVmFsdWUgPSBmbG9vcihzdW0oVmFsdWUsIG5hLnJtID0gVCkpKSAlPiUNCiAgICAgIHNwcmVhZChWYXJpYWJsZSwgVmFsdWUpICU+JQ0KICAgICAgdW5ncm91cCgpICU+JQ0KICAgICAgbGVmdF9qb2luKHllYXJfaGlnaF9tb3J0KQ0KDQoNCndyaXRlX3JkcyhkYXRhLnN1bW1hcnksICIuLi9yZXN1bHRzL3Bsb3RzL3N1bW1hcnkuUmRzIikNCg0KZGF0YS5tb3J0ICU+JSANCiAgZmlsdGVyKFJlZ2lvID09ICJHTTAzNDUiICYgVmFyaWFibGUgJWluJSBjKCJSaXZtIikpICU+JSBhcnJhbmdlKERhdGUpICU+JSANCiAgZ3JvdXBfYnkoUmVnaW8sIFZhcmlhYmxlKSAlPiUgc3VtbWFyaXNlKFZhbHVlID0gc3VtKFZhbHVlLCBuYS5ybSA9IFQpKSAlPiUgc3ByZWFkKFZhcmlhYmxlLCBWYWx1ZSkNCmRhdGEuc3VtbWFyeSAlPiUgZmlsdGVyKFJlZ2lvID09ICJHTTAzNDUiKQ0KYGBgDQoNCg==